package com.tsinghuabigdata.edu.ddmath.module.neteaseim.education.doodle;

import android.text.TextUtils;
import android.util.Log;

import com.facebook.stetho.common.LogUtil;
import com.netease.nimlib.sdk.rts.RTSManager2;
import com.netease.nimlib.sdk.rts.model.RTSTunData;
import com.tsinghuabigdata.edu.ddmath.module.neteaseim.education.doodle.action.DrawCacheManager;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 白板数据收发中心
 * <p>
 * Created by huangjun on 2015/6/29.
 */
public class TransactionCenter {

    private int index = 0;

    private final String TAG = "TransactionCenter";

    // sessionId to TransactionObserver
    private Map<String, TransactionObserver> observers = new HashMap<>(2);

    private Map<String, OnlineStatusObserver> onlineStatusObservers = new HashMap<>(2);

    // <sessionId, <account, transactions>>
    private Map<String, Map<String, List<Transaction>>> syncCache = new HashMap<>();

    private boolean isDoodleViewInited = false;

    public static TransactionCenter getInstance() {
        return TransactionCenterHolder.instance;
    }

    private static class TransactionCenterHolder {
        public static final TransactionCenter instance = new TransactionCenter();
    }

    public void registerObserver(String sessionId, TransactionObserver o) {
        this.observers.put(sessionId, o);
    }

    public void registerOnlineStatusObserver(String sessionId, OnlineStatusObserver o) {
        this.onlineStatusObservers.put(sessionId, o);
    }

    /**
     * 网络变化
     */
    public boolean onNetWorkChange(String sessionId, boolean isCreator) {
        if (onlineStatusObservers.containsKey(sessionId)) {
            return onlineStatusObservers.get(sessionId).onNetWorkChange(isCreator);
        }
        return false;
    }

    /**
     * 数据发送
     */
    public void sendToRemote(String sessionId, String toAccount, List<Transaction> transactions) {
        if (transactions == null || transactions.isEmpty()) {
            return;
        }

        String data = pack(transactions);
        try {
            RTSTunData channelData = new RTSTunData(sessionId, toAccount, data.getBytes
                    ("UTF-8"), data.getBytes().length);
            boolean isSend = RTSManager2.getInstance().sendData(channelData);
            Log.i(TAG, "SEND DATA = " + index + ", BYTES = " + data.getBytes().length + ", isSend=" + isSend);
        } catch (UnsupportedEncodingException e) {
            LogUtil.e("Transaction", "send to remote, getBytes exception : " + data);
        }
    }

    private String pack(List<Transaction> transactions) {
        StringBuilder sb = new StringBuilder();

        List<Transaction> tempList = new ArrayList<>();
        tempList.addAll(transactions);
        for (Transaction t : tempList) {
            sb.append(Transaction.pack(t));
        }

        // 打入序号
//        sb.append(Transaction.packIndex(++index));

        return sb.toString();
    }

    /**
     * 数据接收
     */
    public void onReceive(String sessionId, String account, String data) {
//        data = "11-1-0:0.7615,0.2146,1;12-1-0:0.7577,0.2122,1;12-1-0:0.7462,0.2122,1;12-1-0:0.7308,0.2122,1;12-1-0:0.7077,0.2122,1;12-1-0:0.6885,0.2171,1;12-1-0:0.6615,0.2171,1;12-1-0:0.5846,0.2171,1;12-1-0:0.5192,0.2146,1;12-1-0:0.4231,0.1951,1;12-1-0:0.3269,0.1732,1;12-1-0:0.2846,0.1585,1;12-1-0:0.2769,0.1561,1;12-1-0:0.2769,0.1488,1;" +
//                "12-1-0:0.2923,0.1415,1;12-1-0:0.3385,0.139,1;12-1-0:0.3808,0.139,1;12-1-0:0.4192,0.139,1;12-1-0:0.4462,0.139,1;12-1-0:0.4731,0.1512,1;12-1-0:0.4769,0.1512,1;12-1-0:0.4769,0.1537,1;12-1-0:0.4692,0.1561,1;13-1-0:0.4692,0.1561,1;11-1-0:0.9654,0.1878,1;12-1-0:0.9731,0.1878,1;12-1-0:0.9846,0.1878,1;12-1-0:0.9885,0.1902,1;13-1-0:0.9885,0.1902,1;";
//
//       if (true){
//           Transaction t = new Transaction().make(Transaction.ActionStep.SYNCD, account, data); //// TODO: 2017/3/30
//           List<Transaction> syncDataTrans = unpack(data);
//           DrawCacheManager.getInstance().syncAllUserData(t, syncDataTrans);
//           if (observers.containsKey(sessionId)) {
//               observers.get(sessionId).onCommand(t);
//           }
//           return;
//       }


        List<Transaction> transactions = unpack(data);
        if ((transactions != null ? transactions.size() : 0) <= 0) {
            return;
        }

        List<Transaction> currTransactions = new ArrayList<>();

        for (Transaction t : transactions) {
            String key = DrawCacheManager.getInstance().getDrawcacgeKey(t.getChannel(), t.getCurrentPageNum());
            int step = t.getStep();
            switch (step) {
                case Transaction.ActionStep.SYNCD:
                    List<Transaction> syncDataTrans = unpack(t.getSyncData());
                    DrawCacheManager.getInstance().syncAllUserData(t, syncDataTrans);
                    break;
                case Transaction.ActionStep.SWITCH_CHANNEL:
                    if (observers.containsKey(sessionId)) {
                        observers.get(sessionId).onCommand(t);
                    }
                    break;
                case Transaction.ActionStep.SHOW:
                    //切页后重绘
                    //两步，1。异步加载图片， 2、重绘对应页的笔记，在加载图片成功后再重绘一次
                    if (observers.containsKey(sessionId)) {
                        observers.get(sessionId).onCommand(t);
//                        ImageLoaderKit.getBitmapFromCache()
                    }
                    break;

                case Transaction.ActionStep.IMGMOVE:
                    if (observers.containsKey(sessionId)) {
                        observers.get(sessionId).onCommand(t);
                    }
                    break;
                case Transaction.ActionStep.REVOKE:
                case Transaction.ActionStep.CLEAR:
                    RevokeOrClearCache(sessionId, account, t);
                default:
                    //实时接收的数据，比如说新增的笔记
                    if (DrawCacheManager.getInstance().getCurrKey().equals(key)) {
                        currTransactions.add(t);
                    } else {
                        Map<String, List<Transaction>> tempTransMap = DrawCacheManager.getInstance().getDrawcacheByKey(key);
                        List<Transaction> trans = tempTransMap.get(account);
                        if (trans != null) {
                            trans.add(t);
                        } else {
                            trans = new ArrayList<>();
                            trans.add(t);
                        }
                        tempTransMap.put(account, trans);
                        DrawCacheManager.getInstance().putUserDataMap(key, tempTransMap);
                    }
            }
        }

        //当前页的笔记直接在白板中处理
        if (observers.containsKey(sessionId)) {
            observers.get(sessionId).onTransaction(account, currTransactions);
        }

    }

    private void RevokeOrClearCache(String sessionId, String account, Transaction t) {
        //当前页与非当前页分别处理
        // 白板还没有初始化，收到的信息，存储在syncCache中。若撤回或者清空，不处理，则会数据冗余
        int channel = t.getChannel();
        int page = t.getCurrentPageNum();
        String key = DoodleView.getDrawcacgeKey(channel, page);
        //<account,transtrations>>
        Map<String, List<Transaction>> drawCache = DrawCacheManager.getInstance().getDrawcacheByChannelAndPage(channel, page);
        if (!TransactionCenter.getInstance().isDoodleViewInited()) {
            if (t.getStep() == Transaction.ActionStep.CLEAR) {
                DrawCacheManager.getInstance().clearUserDataMapByKey(key);
            } else if (t.getStep() == Transaction.ActionStep.REVOKE) {
                DrawCacheManager.getInstance().revokeUserDataByKey(key, account);
            }
        }
        //白板已初始化，撤消或清除非当前页的数据
        //如果是当前页的撤消或清除指令，则传入白板处理
        if (DrawCacheManager.getInstance().getCurrentChannel() == t.getChannel() &&
                DrawCacheManager.getInstance().getCurrentPageNum() == t.getCurrentPageNum()) {
            if (observers.containsKey(sessionId)) {
                List<Transaction> currRCTrans = new ArrayList<Transaction>();
                currRCTrans.add(t);
                observers.get(sessionId).onTransaction(account, currRCTrans);
            }
        } else {
            //不是当前页
            if (t.getStep() == Transaction.ActionStep.CLEAR) {
                DrawCacheManager.getInstance().clearUserDataMapByKey(key);
            } else if (t.getStep() == Transaction.ActionStep.REVOKE) {
                DrawCacheManager.getInstance().revokeUserDataByKey(key, account);
            }
        }
    }

    private List<Transaction> unpack(String data) {

        if (TextUtils.isEmpty(data)) {
            return null;
        }

        List<Transaction> transactions = new ArrayList<>();
        String[] pieces = data.split(";");
        for (String p : pieces) {
            Transaction t = Transaction.unpack(p);
            if (t != null) {
                transactions.add(t);
            }
        }

        return transactions;
    }

    public Map<String, List<Transaction>> getSyncDataMap(String sessionId) {
        return syncCache.get(sessionId);
    }

    public Map<String, Map<String, List<Transaction>>> getSyncCache() {
        return syncCache;
    }

    public boolean isDoodleViewInited() {
        return isDoodleViewInited;
    }

    public void setDoodleViewInited(boolean doodleViewInited) {
        isDoodleViewInited = doodleViewInited;
    }
}
